package com.alibaba.citrus.ots.sales.plan.facade.service.salesplan.report;

import com.alibaba.citrus.ots.common.annotation.EpochTransactional;
import com.alibaba.citrus.ots.common.annotation.FacadeInvoker;
import com.alibaba.citrus.ots.common.exception.FacadeException;
import com.alibaba.citrus.ots.common.lock.RedisLock;
import com.alibaba.citrus.ots.common.util.DateUtils;
import com.alibaba.citrus.ots.sales.plan.annotation.CommonRedisLock;
import com.alibaba.citrus.ots.sales.plan.api.salesplan.audit.SalesPlanAuditLineWriteService;
import com.alibaba.citrus.ots.sales.plan.api.salesplan.audit.SalesPlanAuditWriteService;
import com.alibaba.citrus.ots.sales.plan.api.salesplan.report.SalesPlanReportWriteService;
import com.alibaba.citrus.ots.sales.plan.contants.SalesPlanLockKey;
import com.alibaba.citrus.ots.sales.plan.dto.api.request.FlowInstanceStartUpRequest;
import com.alibaba.citrus.ots.sales.plan.dto.api.request.PageQueryPlanLineRequest;
import com.alibaba.citrus.ots.sales.plan.dto.api.request.QueryPlanScItemStatRequest;
import com.alibaba.citrus.ots.sales.plan.dto.api.request.QuerySalesPlanReportRequest;
import com.alibaba.citrus.ots.sales.plan.dto.api.request.QuerySalesPlanRequest;
import com.alibaba.citrus.ots.sales.plan.dto.api.request.SalesPlanReportCallBackRequest;
import com.alibaba.citrus.ots.sales.plan.dto.api.request.SalesPlanReportPageQueryRequest;
import com.alibaba.citrus.ots.sales.plan.dto.api.request.SalesPlanReportRequest;
import com.alibaba.citrus.ots.sales.plan.dto.api.response.FlowInstanceStartUpResponse;
import com.alibaba.citrus.ots.sales.plan.dto.api.response.SalesPlanReportCallBackResponse;
import com.alibaba.citrus.ots.sales.plan.functions.salesplan.report.SalesPlanReportEntity;
import com.alibaba.citrus.ots.sales.plan.model.SalesPlanReportAuditStatusEnum;
import com.alibaba.citrus.ots.sales.plan.model.SalesPlanReportBizTypeEnum;
import com.alibaba.citrus.ots.sales.plan.model.SalesPlanReportStatusEnum;
import com.alibaba.citrus.ots.sales.plan.model.enums.*;
import com.alibaba.citrus.ots.sales.plan.repository.MeshAuditFlowRepository;
import com.alibaba.citrus.ots.sales.plan.repository.PlatformEnhanceRepository;
import com.alibaba.citrus.ots.sales.plan.repository.SalesPlanLineRepository;
import com.alibaba.citrus.ots.sales.plan.repository.SalesPlanReportRepository;
import com.alibaba.citrus.ots.sales.plan.repository.SalesPlanRepository;
import com.alibaba.citrus.ots.sales.plan.repository.SalesPlanScItemStatRepository;
import com.alibaba.citrus.ots.sales.plan.repository.request.OrganizationListQueryRequest;
import com.alibaba.citrus.ots.sales.plan.repository.response.EmployeeRoleResponse;
import com.alibaba.citrus.ots.sales.plan.sdo.SalesPlanAuditLineSDO;
import com.alibaba.citrus.ots.sales.plan.sdo.SalesPlanAuditSDO;
import com.alibaba.citrus.ots.sales.plan.sdo.SalesPlanLineSDO;
import com.alibaba.citrus.ots.sales.plan.sdo.SalesPlanReportSDO;
import com.alibaba.citrus.ots.sales.plan.sdo.SalesPlanSDO;
import com.alibaba.citrus.ots.sales.plan.sdo.SalesPlanStatScItemSDO;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.cz.base.tool.message.ErrorMessage;
import com.alibaba.cz.base.tool.page.PageResult;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.lattice2.epoch.middleware.mq.runtime.EpochMessageService;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.bcots.auditsetting.model.AuditSetting;
import com.epoch.app.bcots.auditsetting.service.AuditSettingService;
import com.epoch.app.bcots.auditsettingdetail.model.AuditSettingDetail;
import com.epoch.app.bcots.auditsettingdetail.service.AuditSettingDetailService;
import com.epoch.app.bcots.contants.BcOtsConstants;
import com.epoch.app.bcots.model.dto.GetAllRolesRequest;
import com.epoch.app.bcots.model.dto.RoleSDO;
import com.epoch.app.bcots.sales_plan.salesplandetail.dto.UpdateSalesPlanDetailResponse;
import com.epoch.app.bcots.sales_plan.salesplandetail.model.SalesPlanDetail;
import com.epoch.app.bcots.sales_plan.salesplandetail.service.SalesPlanDetailService;
import com.epoch.app.bcots.model.dto.AuditSettingDetailLoadListRequest;
import com.epoch.app.bcots.model.dto.AuditSettingLoadListRequest;
import com.epoch.app.bcots.model.enums.AuditSettingStatusEnum;
import com.epoch.app.bcots.model.enums.AuditSettingTypeEnum;
import com.epoch.app.bcots.service.BcOtsService;
import com.epoch.app.otsplatformenhance.enums.OrganizationTypeEnum;
import com.epoch.app.otsplatformenhance.enums.RoleCodeEnum;
import com.epoch.app.otsplatformenhance.sdo.EmployeeSDO;
import com.epoch.app.otsplatformenhance.sdo.OrganizationSDO;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

import static com.alibaba.citrus.ots.sales.plan.contants.SalesPlanLockKey.SALES_PLAN_REPORT_PREFIX;

@Service
public class SalesPlanReportWriteServiceImpl implements SalesPlanReportWriteService {

    private final Log log = Log.getLogger(SalesPlanReportWriteServiceImpl.class);

    @Resource
    private SalesPlanReportRepository salesPlanReportRepository;

    @Resource
    private SalesPlanLineRepository salesPlanLineRepository;

    @Resource
    private SalesPlanAuditWriteService salesPlanAuditWriteService;

    @Resource
    private SalesPlanAuditLineWriteService salesPlanAuditLineWriteService;

    @Resource
    private MeshAuditFlowRepository meshAuditFlowRepository;

    @Resource
    private PlatformEnhanceRepository platformEnhanceRepository;

    @Resource
    private EpochMessageService messageService;

    @Resource
    private SalesPlanRepository salesPlanRepository;

    @Resource
    private SalesPlanScItemStatRepository salesPlanScItemStatRepository;

    @Resource
    private SalesPlanDetailService salesPlanDetailService;

    @Resource(name = "auditSettingServiceImpl")
    private AuditSettingService auditSettingService;


    @Resource(name = "auditSettingDetailServiceImpl")
    private AuditSettingDetailService auditSettingDetailService;

    @Resource
    private BcOtsService bcOtsService;

    private static final String APP_CODE = "bc_ots";

    private static final String PROCESS_CODE = "salesPlanAuditFlowProcess";

    private final static String USER_PREFIX_1 = "user:";

    private final static String USER_PREFIX_2 = "CZ_";

    private final static String PERMIT_LIST = "permitList";
    private final static String LAST_SEQUENCE_LIST = "lastSequenceList";
    private final static String SALES_PLAN_REPORT_SWITCH = "TRUE";

    @Override
    @EpochTransactional(appCode="bc_ots", dataSourceCode = "cr_ots", dataSourceType = "app")
    @FacadeInvoker
    @CommonRedisLock(redisLockPrefix = SALES_PLAN_REPORT_PREFIX)
    public Result<Boolean> report(SalesPlanReportRequest salesPlanReportRequest) {
        // 提报新接口开关，开关打开执行新接口代码
        if (SALES_PLAN_REPORT_SWITCH.equals(BcOtsConstants.SALES_PLAN_REPORT_SWITCH())) {
            return report(salesPlanReportRequest, SALES_PLAN_REPORT_SWITCH);
        }
        log.info("SalesPlanReportWriteService.report.request={}", JSONObject.toJSONString(salesPlanReportRequest));
        // 参数校验
        checkParam(salesPlanReportRequest);
        // 业务限制校验
        checkBizRule(salesPlanReportRequest);
        // 获取提报维度
        SalesPlanReportSDO salesPlanReportSDO = buildSalesPlanReportSDO(salesPlanReportRequest);
        // 是否存在前序提报单
        List<SalesPlanReportSDO> exSalesPlanReportSDOs = fetchPreReport(salesPlanReportSDO);

        String salesPlanReportId;
        // 当前提报单存在
        List<SalesPlanReportSDO> salesPlanReportSDOList = salesPlanReportRepository.querySalesPlanReportList(convertQuerySalesPlanReportRequest(salesPlanReportSDO));
        if (CollectionUtils.isEmpty(salesPlanReportSDOList)) {
            // 生成当前提报单和父级id
            salesPlanReportId = saveReport(salesPlanReportSDO, salesPlanReportRequest);
            // 更新前序提报单
            // refreshPreReport(exSalesPlanReportSDOs, salesPlanReportId);
        } else {
            // 月度计划每个维度只有一个提报单
            SalesPlanReportSDO salesPlanReportSDORecord = salesPlanReportSDOList.get(0);
            // 判断是否有未审批的任务
            if (SalesPlanReportAuditStatusEnum.UNDER_REVIEW.getCode() == salesPlanReportSDORecord.getAuditStatus()) {
                throw new FacadeException(ErrorMessage.code("OTS-02-003-01-16-011"));
            }
            // 更新提报单状态为已提报
            updateReport(salesPlanReportSDORecord);
            salesPlanReportId = salesPlanReportSDORecord.getId();
        }
        //小程序端月度计划提报给月度计划标识
        checkAppletSubmission(salesPlanReportRequest);

        // 设置提报单id
        salesPlanReportSDO.setId(salesPlanReportId);
        // 创建审批流和启动审配引擎
        startUpAuditFlow(salesPlanReportSDO, salesPlanReportRequest);
        // 发送汇总消息，防止页面没有汇总就提报
        String planId = salesPlanReportRequest.getPlanId();
        try {
            // 发消息，触发汇总
            log.info("report_sales_plan_publish_message{}", planId);
            Boolean aBoolean = messageService.sendMessage("sales_plan_publish_message", "CR_SALES_PLAN", "salesPlan_collect", planId);
        } catch (Exception e) {
            log.error("SalesPlanReportWriteServiceImpl#report fail-"+ "提交审批触发月度计划汇总消息发送异常", e);
        }
        return Result.success(true);
    }

    private void checkAppletSubmission(SalesPlanReportRequest salesPlanReportRequest) {
        try {
            if (salesPlanReportRequest.getAppletSubmission()) {
                for (String id : salesPlanReportRequest.getSalesPlanDetailIdList()) {
                    SalesPlanDetail salesPlanDetail = new SalesPlanDetail();
                    salesPlanDetail.setId(Long.parseLong(id));
                    salesPlanDetail.setAppletSubmission(true);
                    UpdateSalesPlanDetailResponse updateSalesPlanDetailResponse = salesPlanDetailService.updateSalesPlanDetail(salesPlanDetail);
                }
            }
        } catch (Exception e) {
            log.error("C端月度计划提报异常checkAppletSubmission " + e.getMessage());
        }
    }

    private void checkBizRule(SalesPlanReportRequest reportRequest) {
        // 只有计划任务需要做校验
        if (!SalesPlanModelEnum.PLAN_MODEL.getModel().equals(reportRequest.getModel())) {
            return;
        }
        // 渠道经理需要校验
        if (!OrganizationTypeEnum.SALES_CHANNEL.getCode().equals(reportRequest.getRelationOrganizationType())) {
            return;
        }
        // 提报人数据权限范围内的计划明细
        PageQueryPlanLineRequest request = new PageQueryPlanLineRequest();
        refreshPageQueryPlanLineRequest(reportRequest, request);
        PageResult<List<SalesPlanLineSDO>> pageResult = salesPlanLineRepository.pageQuerySalesPlanLineList(request);
        if (null != pageResult && CollectionUtils.isNotEmpty(pageResult.getContent())) {
            throw new FacadeException(ErrorMessage.code("OTS-02-003-01-16-021"));
        }
    }

    private void refreshPageQueryPlanLineRequest(SalesPlanReportRequest reportRequest, PageQueryPlanLineRequest request) {
        if (reportRequest.getIsSales()) {
            request.setManageEmployeeId(reportRequest.getOperatorId());
        } else {
            OrganizationTypeEnum organizationTypeEnum = OrganizationTypeEnum.of(reportRequest.getRelationOrganizationType());
            switch (organizationTypeEnum) {
                case COMPANY:
                    request.setOrgBusinessUnitCode(reportRequest.getRelationOrganizationId());
                    break;
                case SALES_ORGANIZATION:
                    request.setOrgSalesOrganizationCode(reportRequest.getRelationOrganizationId());
                    break;
                case SALES_CHANNEL:
                    request.setOrgSalesChannelCode(reportRequest.getRelationOrganizationId());
                    break;
                case SALES_DEPARTMENT:
                    request.setOrgSalesDepartmentCode(reportRequest.getRelationOrganizationId());
                    break;
                default:
            }
        }
        request.setPlanId(reportRequest.getPlanId());
        // 标识提报量小于1
        request.setMonthCount(1);
        request.setStart(0);
        request.setLimit(1);
    }

    private SalesPlanReportSDO buildSalesPlanReportSDO(SalesPlanReportRequest salesPlanReportRequest) {
        // 获取提拔单维度信息
        SalesPlanReportSDO salesPlanReportSDO = getReportDimension(salesPlanReportRequest);
        // 属性封装
        salesPlanReportSDO.setPlanId(salesPlanReportRequest.getPlanId());
        salesPlanReportSDO.setModel(salesPlanReportRequest.getModel());
        salesPlanReportSDO.setModelId(salesPlanReportRequest.getModelId());
        salesPlanReportSDO.setPlanTime(salesPlanReportRequest.getPlanTime());
        salesPlanReportSDO.setReportEmployeeId(salesPlanReportRequest.getOperatorId());
        salesPlanReportSDO.setAuditStatus(SalesPlanReportAuditStatusEnum.UNDER_REVIEW.getCode());
        salesPlanReportSDO.setCreatorId(salesPlanReportRequest.getOperatorId());
        salesPlanReportSDO.setModifierId(salesPlanReportRequest.getOperatorId());
        return salesPlanReportSDO;
    }

    private void updateReport(SalesPlanReportSDO salesPlanReportSDORecord) {
        SalesPlanReportSDO salesPlanReportSDO = new SalesPlanReportSDO();
        salesPlanReportSDO.setId(salesPlanReportSDORecord.getId());
        salesPlanReportSDO.setStatus(SalesPlanReportStatusEnum.REPORTED.getCode());
        salesPlanReportSDO.setAuditStatus(SalesPlanReportAuditStatusEnum.UNDER_REVIEW.getCode());
        salesPlanReportSDO.setGmtModified(new Date());
        SalesPlanReportEntity salesPlanReportEntity = SalesPlanReportEntity.of(salesPlanReportSDO);
        Boolean edit = salesPlanReportEntity.edit();
        if (!edit) {
            throw new FacadeException(ErrorMessage.code("OTS-02-003-01-16-010"));
        }
    }

    private void startUpAuditFlow(SalesPlanReportSDO salesPlanReportSDO, SalesPlanReportRequest salesPlanReportRequest) {
        // 创建审批单
        String auditId = createSalesPlanAudit(salesPlanReportSDO);
        // 插入审批单明细（快照）TODO 审核单明细暂时不保存
        // createSalesPlanAuditLine(auditId, salesPlanReportSDO);
        // 创建纪元审批流实例、并启动（审批单ID）
        FlowInstanceStartUpResponse flowInstanceStartUpResponse = null;
        try {
            List<String> auditorIdList = getAuditorList(salesPlanReportRequest.getRelationOrganizationId(), salesPlanReportSDO.getBizType(), salesPlanReportRequest.getIsSales(), salesPlanReportRequest.getModel());
            flowInstanceStartUpResponse = startUpAudit(auditId, salesPlanReportSDO, auditorIdList);
            log.info("启动审批流返回结果：{}", JSONObject.toJSONString(flowInstanceStartUpResponse));
        } catch (FacadeException facadeException) {
            log.error("SalesPlanReportWriteServiceImpl#report_fail " + "启动审批流发生异常:{}-{}", facadeException.getErrorCode(), facadeException.getErrorMessage());
            throw facadeException;
        } catch (Exception e) {
            log.error("SalesPlanReportWriteServiceImpl#report_fail " + "启动审批流异常", e);
            throw new FacadeException(ErrorMessage.code("OTS-02-003-01-16-012"));
        }
    }

    private void refreshPreReport(List<SalesPlanReportSDO> exSalesPlanReportSDOs, String salesPlanReportId) {
        if (CollectionUtils.isNotEmpty(exSalesPlanReportSDOs)) {
            exSalesPlanReportSDOs.forEach(salesPlanReportSDOForEx -> {
                // 前序提报单的parentId
                salesPlanReportSDOForEx.setParentId(salesPlanReportId);
                salesPlanReportSDOForEx.setGmtModified(new Date());
                SalesPlanReportEntity salesPlanReportEntityForEx = SalesPlanReportEntity.of(salesPlanReportSDOForEx);
                Boolean exEdit = salesPlanReportEntityForEx.edit();
                if (!exEdit) {
                    throw new FacadeException(ErrorMessage.code("OTS-02-003-01-16-010"));
                }
            });
        }
    }

    private String saveReport(SalesPlanReportSDO salesPlanReportSDO, SalesPlanReportRequest reportRequest) {
        //  构造当前维度提报单
        SalesPlanReportSDO salesPlanSDOForCreate = new SalesPlanReportSDO();
        BeanUtils.copyProperties(salesPlanReportSDO, salesPlanSDOForCreate);
        salesPlanSDOForCreate.setStatus(SalesPlanReportStatusEnum.REPORTED.getCode());
        // 构造父级维度提报单
        buildParentSalesPlanReportId(salesPlanSDOForCreate, reportRequest);
        // 保存提报单
        SalesPlanReportEntity salesPlanReportEntity = SalesPlanReportEntity.of(salesPlanSDOForCreate);
        return salesPlanReportEntity.save();
    }

    private void buildParentSalesPlanReportId(SalesPlanReportSDO reportSDO, SalesPlanReportRequest reportRequest) {
        // 获取审批汇总的上一级
        Integer upOrganizationType = fetchUpOneLevelOrgType(reportSDO, reportRequest);
        if (upOrganizationType < 0) {
            return;
        }
        // 获取当前组织向上回溯指定类型组织列表
        List<OrganizationSDO> organizationSDOList = platformEnhanceRepository.getTopOrganizationList(convert(reportRequest.getRelationOrganizationId(), upOrganizationType));
        if (CollectionUtils.isEmpty(organizationSDOList)) {
            throw new FacadeException(ErrorMessage.code("OTS-02-003-01-16-013"));
        }
        // 获取最后一个组织即可
        OrganizationSDO organizationSDO = organizationSDOList.get(organizationSDOList.size() - 1);
        reportSDO.setParentId(organizationSDO.getId());
    }

    private Integer fetchUpOneLevelOrgType(SalesPlanReportSDO reportSDO, SalesPlanReportRequest reportRequest) {
        // 调整审批只有一级，不用建上一级提报单
        if (SalesPlanModelEnum.ADJUST_MODEL.getModel().equals(reportRequest.getModel())) {
            return -1;
        }
        // 月度计划提报汇总上一级组织类型
        if (reportRequest.getIsSales()) {
            return OrganizationTypeEnum.SALES_CHANNEL.getCode();
        } else if (SalesPlanReportBizTypeEnum.CHANNEL_REPORT.getCode().equals(reportSDO.getBizType())) {
            return OrganizationTypeEnum.COMPANY.getCode();
        } else if (SalesPlanReportBizTypeEnum.BUSINESS_DIMENSION_REPORT.getCode().equals(reportSDO.getBizType())) {
            return -1;
        }
        return -1;
    }

    private List<SalesPlanReportSDO> fetchPreReport(SalesPlanReportSDO salesPlanReportSDO) {
        List<SalesPlanReportSDO> exSalesPlanReportSDOs = Lists.newArrayList();
        //  业务员属于最低一级提报，不需要查询子（下一级）提报单
        if (!SalesPlanReportBizTypeEnum.PROMOTER_REPORT.getCode().equals(salesPlanReportSDO.getBizType())) {
            QuerySalesPlanReportRequest exQuerySalesPlanReportRequest = new QuerySalesPlanReportRequest();
            exQuerySalesPlanReportRequest.setPlanId(salesPlanReportSDO.getPlanId());
            exQuerySalesPlanReportRequest.setModelId(salesPlanReportSDO.getModelId());
            exQuerySalesPlanReportRequest.setModel(salesPlanReportSDO.getModel());
            exQuerySalesPlanReportRequest.setParentId(salesPlanReportSDO.getBizId());
            // 判断是否有未完成的子提报单
            exSalesPlanReportSDOs = salesPlanReportRepository.querySalesPlanReportList(exQuerySalesPlanReportRequest);
            if (CollectionUtils.isNotEmpty(exSalesPlanReportSDOs)) {
                // 判断子提审单是否都完成  通过认定为终态
                boolean flag = exSalesPlanReportSDOs.stream().anyMatch(s -> s.getAuditStatus() != SalesPlanReportAuditStatusEnum.APPROVED.getCode());
                // 前序未审核完成, 不能创建提报单
                if (flag) {
                    throw new FacadeException(ErrorMessage.code("OTS-02-003-01-16-008"));
                }
            } else {
                // 无前序提报单，需要报错
                throw new FacadeException(ErrorMessage.code("OTS-02-003-01-16-009"));
            }
        }
        return exSalesPlanReportSDOs;
    }

    private QuerySalesPlanReportRequest convertQuerySalesPlanReportRequest(SalesPlanReportSDO request) {
        QuerySalesPlanReportRequest querySalesPlanReportRequest = new QuerySalesPlanReportRequest();
        querySalesPlanReportRequest.setPlanId(request.getPlanId());
        querySalesPlanReportRequest.setBizType(request.getBizType());
        querySalesPlanReportRequest.setBizId(request.getBizId());
        querySalesPlanReportRequest.setModel(request.getModel());
        querySalesPlanReportRequest.setModelId(request.getModelId());
        return querySalesPlanReportRequest;
    }

    /**
     * 获取审批人列表
     *
     * @param organizationId
     * @param bizType
     * @param isSales
     * @param modelType
     * @return
     */
    private List<String> getAuditorList(String organizationId, Integer bizType, boolean isSales, Integer modelType) {
        // 获取审批汇总的上一级
        Integer upOrganizationType = getUpOneLevel(bizType, isSales, modelType);
        // 获取当前组织向上回溯指定类型组织列表
        List<OrganizationSDO> organizationSDOList = platformEnhanceRepository.getTopOrganizationList(convert(organizationId, upOrganizationType));
        if (CollectionUtils.isEmpty(organizationSDOList)) {
            throw new FacadeException(ErrorMessage.code("OTS-02-003-01-16-013"));
        }
        // 获取最后一个组织即可
        OrganizationSDO organizationSDO = organizationSDOList.get(organizationSDOList.size() - 1);
        // 获取组织下所有的用户
        List<EmployeeSDO> employeeSDOS = platformEnhanceRepository.getEmployeeList(organizationSDO.getId(), 1);
        if (CollectionUtils.isEmpty(employeeSDOS)) {
            throw new FacadeException(ErrorMessage.code("OTS-02-003-01-16-014"));
        }
        // 根据角色过滤
        List<String> auditorIdList = filterEmployeeByRole(bizType, employeeSDOS, modelType);
        if (CollectionUtils.isEmpty(auditorIdList)) {
            throw new FacadeException(ErrorMessage.code("OTS-02-003-01-16-014"));
        }
        return auditorIdList.stream().map(id -> "CZ_" + id).collect(Collectors.toList());
    }

    /**
     * 根据角色筛选员工id
     * 主要解决同一组织多个角色问题
     *
     * @param bizType
     * @param employeeSDOS
     * @param modelType
     * @return
     */
    private List<String> filterEmployeeByRole(Integer bizType, List<EmployeeSDO> employeeSDOS, Integer modelType) {
        // 调整获取审核列表
        if (SalesPlanModelEnum.ADJUST_MODEL.getModel().equals(modelType)) {
            // 调整业务员提交的审批单，由调度员审批
            return filterForAdjust(employeeSDOS);
        }
        // 销售渠道提交的审批单，由调度员审批
        if (SalesPlanReportBizTypeEnum.CHANNEL_REPORT.getCode().equals(bizType)) {
            return filter(employeeSDOS, RoleCodeEnum.PLAN_DISPATCHER.getCode()).stream().map(EmployeeSDO::getId).collect(Collectors.toList());
        }
        // 业务单元提交的审批单，由副总/总经理审批
        if (SalesPlanReportBizTypeEnum.BUSINESS_DIMENSION_REPORT.getCode().equals(bizType)) {
            return filter(employeeSDOS, RoleCodeEnum.GENERAL_MANAGER.getCode()).stream().map(EmployeeSDO::getId).collect(Collectors.toList());
        }

        return employeeSDOS.stream().map(EmployeeSDO::getId).collect(Collectors.toList());
    }

    private List<String> filterForAdjust(List<EmployeeSDO> employeeSDOS) {
        return filter(employeeSDOS, RoleCodeEnum.PLAN_DISPATCHER.getCode()).stream().map(EmployeeSDO::getId).collect(Collectors.toList());
    }

    private List<EmployeeSDO> filter(List<EmployeeSDO> employeeSDOS, String roleCode) {
        return employeeSDOS.stream().filter(employeeSDO -> filterRole(employeeSDO.getId(), roleCode)).collect(Collectors.toList());
    }

    private boolean filterRole(String employeeId, String roleCode) {
        List<EmployeeRoleResponse> employeeRoleResponses = platformEnhanceRepository.getEmployeeRoleListById(employeeId, 1);
        if (CollectionUtils.isEmpty(employeeRoleResponses)) {
            return false;
        }
        return employeeRoleResponses.stream().anyMatch(employeeRoleResponse -> roleCode.equals(employeeRoleResponse.getCode()));
    }

    /**
     * 获取汇总上一级类型
     *
     * @param bizType
     * @param isSales
     * @return
     */
    private Integer getUpOneLevel(Integer bizType, boolean isSales, Integer modelType) {
        // 调整审批只有一级，业务员到计划调度员
        if (SalesPlanModelEnum.ADJUST_MODEL.getModel().equals(modelType)) {
            return getUpOneLevelForAdjust(isSales);
        }
        // 月度计划提报汇总上一级类型
        if (isSales) {
            return OrganizationTypeEnum.SALES_CHANNEL.getCode();
        } else if (SalesPlanReportBizTypeEnum.CHANNEL_REPORT.getCode().equals(bizType)) {
            return OrganizationTypeEnum.COMPANY.getCode();
        } else if (SalesPlanReportBizTypeEnum.BUSINESS_DIMENSION_REPORT.getCode().equals(bizType)) {
            return OrganizationTypeEnum.COMPANY.getCode();
        }
        return 0;
    }

    /**
     * 获取汇总上一级类型
     * 调整使用
     * @param isSales
     * @return
     */
    private Integer getUpOneLevelForAdjust(boolean isSales) {
        if (isSales) {
            return OrganizationTypeEnum.COMPANY.getCode();
        }
        return 0;
    }

    private OrganizationListQueryRequest convert(String organizationId, Integer bizType) {
        OrganizationListQueryRequest topOrganizationListRequest = new OrganizationListQueryRequest();
        topOrganizationListRequest.setId(organizationId);
        topOrganizationListRequest.setType(bizType);
        return topOrganizationListRequest;
    }

    private void checkParam(SalesPlanReportRequest salesPlanReportRequest) {
        if (StringUtils.isBlank(salesPlanReportRequest.getPlanId())) {
            throw new FacadeException(ErrorMessage.code("OTS-02-002-01-15-006", "月度计划ID不能为空"));
        }
        if (null == salesPlanReportRequest.getModel()) {
            throw new FacadeException(ErrorMessage.code("OTS-02-002-01-15-006", "业务类型不能为空"));
        }
        if (null == salesPlanReportRequest.getModelId()) {
            throw new FacadeException(ErrorMessage.code("OTS-02-002-01-15-006", "业务id不能为空"));
        }
        if (null == salesPlanReportRequest.getRelationOrganizationType()) {
            throw new FacadeException(ErrorMessage.code("OTS-02-002-01-15-006", "提报人关联组织类型不能为空"));
        }
        if (StringUtils.isBlank(salesPlanReportRequest.getRelationOrganizationId())) {
            throw new FacadeException(ErrorMessage.code("OTS-02-002-01-15-006", "提报人关联组织不能为空"));
        }
        //角色string转list
        if (StringUtils.isEmpty(salesPlanReportRequest.getRoleCodeString())) {
            throw new FacadeException(ErrorMessage.code("OTS-02-002-01-15-006", "提报人角色不能为空"));
        }
        List<String> roleCodes = Lists.newArrayList();
        try {
            String[] roleList = salesPlanReportRequest.getRoleCodeString().replace("[", "").replace("]", "")
                    .replace("\"","").split(",");
            for (String s : roleList) {
                s = s.trim();
                roleCodes.add(s);
            }
            salesPlanReportRequest.setRoleCodes(roleCodes);
        } catch (Exception e) {
            log.info("SalesPlanReportWriteService.report.转换角色失败={}", e);
            throw new FacadeException("角色信息转换失败");
        }
        if (CollectionUtils.isEmpty(roleCodes)) {
            throw new FacadeException(ErrorMessage.code("OTS-02-002-01-15-006", "提报人角色不能为空"));
        }
    }

    /**
     * 获取提报维度
     * 封装提报单SDO
     *
     * @param salesPlanReportRequest
     * @return
     */
    private SalesPlanReportSDO getReportDimension(SalesPlanReportRequest salesPlanReportRequest) {
        Integer relationOrganizationType = salesPlanReportRequest.getRelationOrganizationType();
        SalesPlanReportSDO salesPlanReportSDO = new SalesPlanReportSDO();
        salesPlanReportSDO.setIsLeafTask(0);
        // 1、业务员（业务员角色）
        if (salesPlanReportRequest.getIsSales()) {
            salesPlanReportSDO.setBizType(SalesPlanReportBizTypeEnum.PROMOTER_REPORT.getCode());
            salesPlanReportSDO.setBizId(salesPlanReportRequest.getOperatorId());
            salesPlanReportSDO.setIsLeafTask(1);
        }
        // 3、销售渠道（渠道经理角色）
        else if (OrganizationTypeEnum.SALES_CHANNEL.getCode().equals(relationOrganizationType)) {
            salesPlanReportSDO.setBizType(SalesPlanReportBizTypeEnum.CHANNEL_REPORT.getCode());
            salesPlanReportSDO.setBizId(salesPlanReportRequest.getRelationOrganizationId());
        }
        // 5、业务单元（调度员/总经理角色）
        else if (OrganizationTypeEnum.COMPANY.getCode().equals(relationOrganizationType)) {
            salesPlanReportSDO.setBizType(SalesPlanReportBizTypeEnum.BUSINESS_DIMENSION_REPORT.getCode());
            salesPlanReportSDO.setBizId(salesPlanReportRequest.getRelationOrganizationId());
        }
        // 其他角色先默认为业务员（如：平台超级管理员）
        else {
            salesPlanReportSDO.setBizType(SalesPlanReportBizTypeEnum.PROMOTER_REPORT.getCode());
            salesPlanReportSDO.setBizId(salesPlanReportRequest.getOperatorId());
            salesPlanReportSDO.setIsLeafTask(1);
        }
        return salesPlanReportSDO;
    }

    /**
     * 创建提审单
     *
     * @param salesPlanReportSDO
     * @return
     */
    private String createSalesPlanAudit(SalesPlanReportSDO salesPlanReportSDO) {
        SalesPlanAuditSDO salesPlanAuditSDO = new SalesPlanAuditSDO();
        // 计划id
        salesPlanAuditSDO.setPlanId(salesPlanReportSDO.getPlanId());
        // 创建审批单 默认是待审核状态
        salesPlanAuditSDO.setAuditStatus(SalePlanAuditStatusEnum.RUNNING.getCode());
        // 审核发起人
        salesPlanAuditSDO.setAuditInitiatorId(salesPlanReportSDO.getReportEmployeeId().replace(USER_PREFIX_2, ""));
        // 提报单id
        salesPlanAuditSDO.setReportOrderId(salesPlanReportSDO.getId());
        salesPlanAuditSDO.setCreatorId(salesPlanReportSDO.getCreatorId());
        salesPlanAuditSDO.setModifierId(salesPlanReportSDO.getModifierId());
        salesPlanAuditSDO.setGmtModified(new Date());
        salesPlanAuditSDO.setGmtCreate(new Date());
        Result<String> createSalesPlanAuditResult = salesPlanAuditWriteService.create(salesPlanAuditSDO);
        return createSalesPlanAuditResult.getResult();
    }

    /**
     * 更新提审单
     * 主要关联审批流程实例id
     * 目前由审批任务回调时同步更新
     *
     * @param
     * @return
     */
    private Boolean editSalesPlanAudit(String auditId, FlowInstanceStartUpResponse flowInstanceStartUpResponse) {
        SalesPlanAuditSDO salesPlanAuditSDO = new SalesPlanAuditSDO();
        // 提报单id
        salesPlanAuditSDO.setId(auditId);
        // 审核流程实例id
        salesPlanAuditSDO.setFlowInstanceId(flowInstanceStartUpResponse.getInstanceId());
        salesPlanAuditSDO.setAuditInitiatorId(flowInstanceStartUpResponse.getCreatorId());
        Result<Boolean> edit = salesPlanAuditWriteService.edit(salesPlanAuditSDO);
        return edit.getResult();
    }

    /**
     * 创建提审单明细（月度计划明细快照+审批单id）
     *
     * @param auditId
     * @param salesPlanReportSDO
     * @return
     */
    private Boolean createSalesPlanAuditLine(String auditId, SalesPlanReportSDO salesPlanReportSDO) {
        PageQueryPlanLineRequest pageQueryPlanLineRequest = new PageQueryPlanLineRequest();
        pageQueryPlanLineRequest.setPlanId(salesPlanReportSDO.getPlanId());
        pageQueryPlanLineRequest.setLimit(1000);
        // 这里要根据业务维度封装查询条件
        Integer bizType = salesPlanReportSDO.getBizType();
        PageResult<List<SalesPlanLineSDO>> querySalesPlanLineList = salesPlanLineRepository.pageQuerySalesPlanLineList(pageQueryPlanLineRequest);
        if (null == querySalesPlanLineList || CollectionUtils.isEmpty(querySalesPlanLineList.getContent())) {
            return true;
        }
        List<SalesPlanAuditLineSDO> salesPlanAuditLineSDOList = querySalesPlanLineList.getContent().stream().map(salesPlanLineSDO -> {
            SalesPlanAuditLineSDO salesPlanAuditLineSDO = new SalesPlanAuditLineSDO();
            BeanUtils.copyProperties(salesPlanLineSDO, salesPlanAuditLineSDO);
            salesPlanAuditLineSDO.setAuditOrderId(auditId);
            return salesPlanAuditLineSDO;
        }).collect(Collectors.toList());
        Result<Boolean> booleanResult = salesPlanAuditLineWriteService.batchCreate(salesPlanAuditLineSDOList);
        return booleanResult.getResult();
    }

    /**
     * 启动纪元审批流
     * @param auditId
     * @param salesPlanReportSDO
     * @param auditorIdList
     * @return
     */
    private FlowInstanceStartUpResponse startUpAudit(String auditId, SalesPlanReportSDO salesPlanReportSDO, List<String> auditorIdList) {
        FlowInstanceStartUpRequest flowInstanceStartUpRequest = new FlowInstanceStartUpRequest();
        flowInstanceStartUpRequest.setAppCode(APP_CODE);
        flowInstanceStartUpRequest.setProcessCode(PROCESS_CODE);
        Map<String, Object> map = Maps.newHashMap();
        map.put("id", auditId);
        map.put("reportOrderId", salesPlanReportSDO.getId());
        map.put("planId", salesPlanReportSDO.getPlanId());
        map.put("planTime", DateUtils.dateToStamp(salesPlanReportSDO.getPlanTime()));
        map.put("auditorIdList", auditorIdList);
        Object body = JSON.parseObject(JSON.toJSONString(map), Object.class);
        flowInstanceStartUpRequest.setBody(body);
        return meshAuditFlowRepository.startDefaultProcess(flowInstanceStartUpRequest);
    }

    @Override
    @FacadeInvoker
    public Result<Boolean> reOpen(SalesPlanReportSDO salesPlanReportSDO) {
        // 校验
        checkReportReOpen(salesPlanReportSDO);
        // 获取前序提报单
        List<SalesPlanReportSDO> salesPlanReportSDOList = fetchPreReportByParent(salesPlanReportSDO);
        // 前序提报单状态变更，生成新审批单
        processPreReport(salesPlanReportSDOList);
        return Result.success(true);
    }

    @Override
    @FacadeInvoker
    public Result<Boolean> submitToCRM(SalesPlanReportRequest salesPlanReportRequest) {
        try (RedisLock lock = new RedisLock(BcOtsConstants.REDIS_CACHE_CODE(), SalesPlanLockKey.getPlanSubmitToCRMLockKey(salesPlanReportRequest.getPlanId()))) {
            boolean locked = lock.lock();
            if (!locked) {
                log.error("SalesPlanReportWriteServiceImpl#submitToCRM.getLock.fail planId=" + salesPlanReportRequest.getPlanId());
                return Result.fail("OTS-02-006-00-16-006", "正在提报CRM中，请稍后重试");
            }
            // 查询业务单元货品维度的月都计划汇总数据
            QueryPlanScItemStatRequest queryPlanScItemStatRequest = new QueryPlanScItemStatRequest();
            queryPlanScItemStatRequest.setPlanId(Long.valueOf(salesPlanReportRequest.getPlanId()));
            queryPlanScItemStatRequest.setBizType(SalesStatBizTypeEnum.BUSINESS_UNIT.getBizType());
            queryPlanScItemStatRequest.setPoolType(String.valueOf(StatPoolTypeEnum.SC_ITEM.getPoolType()));
            queryPlanScItemStatRequest.setStart(0);
            queryPlanScItemStatRequest.setLimit(1000);
            PageResult<List<SalesPlanStatScItemSDO>> pageResult = salesPlanScItemStatRepository.batchQueryPlanScItemByBizId(queryPlanScItemStatRequest);
            List<SalesPlanStatScItemSDO> salesPlanStatScItemSDOS = pageResult.getContent();
            // 发送消息至集成应用
            String message = JSONObject.toJSONString(salesPlanStatScItemSDOS);
            Boolean aBoolean = messageService.sendMessage("sales_plan_create_message", "CR_SALES_PLAN", "SalesPlan_create", message);
            return Result.success(aBoolean);
        } catch (FacadeException e) {
            log.error("SalesPlanReportWriteServiceImpl#submitToCRM_fail ", e);
            throw new FacadeException(e.getErrorCode(), e.getErrorMessage());
        }
    }

    /**
     * 更新提报单
     *
     * @param salesPlanReportSDO
     * @return
     */
    @Override
    @FacadeInvoker
    public Result<Boolean> edit(SalesPlanReportSDO salesPlanReportSDO) {
        log.info("SalesPlanReportWriteService.edit.request={}", JSONObject.toJSONString(salesPlanReportSDO));
        SalesPlanReportEntity salesPlanReportEntity = SalesPlanReportEntity.of(salesPlanReportSDO);
        salesPlanReportEntity.edit();
        return Result.success(true);
    }

    @Override
    @FacadeInvoker
    public Result<SalesPlanReportCallBackResponse> submitToCRMCallBack(SalesPlanReportCallBackRequest salesPlanReportCallBackRequest) {
        SalesPlanReportCallBackResponse callBackResponse = new SalesPlanReportCallBackResponse();
        if (!salesPlanReportCallBackRequest.getSuccess()) {
            callBackResponse.setMessage(salesPlanReportCallBackRequest.getMessage());
            callBackResponse.setSuccess(salesPlanReportCallBackRequest.getSuccess());
            callBackResponse.setPlanId(salesPlanReportCallBackRequest.getInnerKey());
            log.error("SalesPlanReportWriteServiceImpl#submitToCRMCallBack_fail :{}-{}", salesPlanReportCallBackRequest.getInnerKey(), salesPlanReportCallBackRequest.getMessage());
            return Result.success(callBackResponse);
        }
        if (StringUtils.isBlank(salesPlanReportCallBackRequest.getInnerKey())) {
            callBackResponse.setMessage("innerKey不可为空");
            callBackResponse.setSuccess(false);
            callBackResponse.setPlanId(salesPlanReportCallBackRequest.getInnerKey());
            log.error("SalesPlanReportWriteServiceImpl#submitToCRMCallBack_fail " + callBackResponse.getMessage());
            return Result.success(callBackResponse);
        }
        QuerySalesPlanRequest querySalesPlanRequest = new QuerySalesPlanRequest();
        querySalesPlanRequest.setId(salesPlanReportCallBackRequest.getInnerKey());
        SalesPlanSDO salesPlanSDO = salesPlanRepository.load(querySalesPlanRequest);
        if (Objects.isNull(salesPlanSDO)) {
            callBackResponse.setMessage("未查到月度计划,planId:" + salesPlanReportCallBackRequest.getInnerKey());
            callBackResponse.setSuccess(false);
            callBackResponse.setPlanId(salesPlanReportCallBackRequest.getInnerKey());
            log.warn("SalesPlanReportWriteServiceImpl#submitToCRMCallBack_fail " + callBackResponse.getMessage());
            return Result.success(callBackResponse);
        }
        if (!salesPlanSDO.getStatus().equals(SalesPlanStatusEnum.TO_BE_SYNC.getCode())) {
            callBackResponse.setMessage("该月度计划不是待同步的单据,planId：" + salesPlanReportCallBackRequest.getInnerKey());
            callBackResponse.setSuccess(false);
            callBackResponse.setPlanId(salesPlanReportCallBackRequest.getInnerKey());
            log.warn("SalesPlanReportWriteServiceImpl#submitToCRMCallBack_fail " + callBackResponse.getMessage());
            return Result.success(callBackResponse);
        }
        SalesPlanSDO updateRequest = new SalesPlanSDO();
        updateRequest.setId(Long.valueOf(salesPlanReportCallBackRequest.getInnerKey()));
        updateRequest.setStatus(SalesPlanStatusEnum.TO_BE_REPLIED.getCode());
        Integer count = salesPlanRepository.updateSalesPlanStatus(updateRequest);
        if (count == 1) {
            callBackResponse.setMessage(salesPlanReportCallBackRequest.getMessage());
            callBackResponse.setSuccess(salesPlanReportCallBackRequest.getSuccess());
            callBackResponse.setPlanId(salesPlanReportCallBackRequest.getInnerKey());
        }
        return Result.success(callBackResponse);
    }

    private List<SalesPlanReportSDO> fetchPreReportByParent(SalesPlanReportSDO salesPlanReportSDO) {
        SalesPlanReportPageQueryRequest request = new SalesPlanReportPageQueryRequest();
        request.setParentId(salesPlanReportSDO.getBizId());
        request.setPlanId(salesPlanReportSDO.getPlanId());
        request.setModelId(salesPlanReportSDO.getModelId());
        request.setModelType(salesPlanReportSDO.getModel());
        request.setAuditStatus(SalesPlanReportAuditStatusEnum.APPROVED.getCode());
        request.setStart(0);
        request.setLimit(200);
        PageResult<List<SalesPlanReportSDO>> pageResult = salesPlanReportRepository.pageQuery(request);
        if (null == pageResult || pageResult.getTotal() < 1) {
            log.warn("提报单id:{}没有审批完成的前序提报单, 请检查数据", salesPlanReportSDO.getId());
            return null;
        }
        return pageResult.getContent();
    }

    private void checkReportReOpen(SalesPlanReportSDO salesPlanReportSDO) {
        if (null == salesPlanReportSDO || StringUtils.isBlank(salesPlanReportSDO.getId())) {
            throw new FacadeException(ErrorMessage.code("OTS-02-002-01-15-020"));
        }
    }

    private void initPreReportStatus(SalesPlanReportSDO reportSDO) {
        SalesPlanReportSDO salesPlanReportSDO = new SalesPlanReportSDO();
        salesPlanReportSDO.setStatus(SalesPlanReportStatusEnum.REPORTED.getCode());
        salesPlanReportSDO.setAuditStatus(SalesPlanReportAuditStatusEnum.UNDER_REVIEW.getCode());
        salesPlanReportSDO.setGmtModified(new Date());
        salesPlanReportSDO.setId(reportSDO.getId());
        SalesPlanReportEntity salesPlanReportEntity = SalesPlanReportEntity.of(salesPlanReportSDO);
        Boolean edit = salesPlanReportEntity.edit();
        if (!edit) {
            throw new FacadeException(ErrorMessage.code("OTS-02-002-01-16-021"));
        }
    }

    private void processPreReport(List<SalesPlanReportSDO> planReportSDOList) {
        Optional.ofNullable(planReportSDOList).orElse(Lists.newArrayList()).forEach(salesPlanReportSDO -> {
            // 更新前序提报单状态
            initPreReportStatus(salesPlanReportSDO);
            // 创建审批单
            String auditId = createSalesPlanAudit(salesPlanReportSDO);
            // 创建纪元审批流实例、并启动（审批单ID）
            FlowInstanceStartUpResponse flowInstanceStartUpResponse = null;
            try {
                List<String> auditorIdList = fetchAuditorIdList(salesPlanReportSDO);
                flowInstanceStartUpResponse = startUpAudit(auditId, salesPlanReportSDO, auditorIdList);
                log.info("启动审批流返回结果：{}", JSONObject.toJSONString(flowInstanceStartUpResponse));
            } catch (FacadeException e) {
                log.error("SalesPlanReportWriteServiceImpl#reOpen_fail " + "启动审批流发生异常异常:{}-{}", e.getErrorCode(), e.getErrorMessage());
                throw e;
            } catch (Exception e) {
                log.error("SalesPlanReportWriteServiceImpl#reOpen_fail " + "启动审批流异常", e);
                throw new FacadeException(ErrorMessage.code("OTS-02-003-01-16-012"));
            }
        });
    }

    private List<String> fetchAuditorIdList(SalesPlanReportSDO salesPlanReportSDO) {
        if (StringUtils.isBlank(salesPlanReportSDO.getFeatures())) {
            throw new FacadeException(ErrorMessage.code("OTS-02-002-01-16-022"));
        }
        JSONObject jsonObject = JSONObject.parseObject(salesPlanReportSDO.getFeatures());
        JSONArray jsonArray = JSON.parseArray(jsonObject.getString("auditorIdList"));
        List<String> auditorIdList = Lists.newArrayList();
        jsonArray.forEach(o -> auditorIdList.add(StringUtils.replace(String.valueOf(o), USER_PREFIX_1,"")));
        return auditorIdList;
    }

    /**
     * 通过审批节点配置创建月度计划提报单
     * @param salesPlanReportRequest 入参
     * @return 结果
     */
    public Result<Boolean> report(SalesPlanReportRequest salesPlanReportRequest, String str) {
        log.info("SalesPlanReportWriteService.report.request=" + JSONObject.toJSONString(salesPlanReportRequest));
        // 参数校验
        checkParam(salesPlanReportRequest);
        //小程序端月度计划提报给月度计划标识
        checkAppletSubmission(salesPlanReportRequest);
        // step1、通过当前提报人的组织类型判断当前提报人是否在销售渠道组织中，若在，通过当前组织id查询对应的审批节点，未找到返回；
        //        若组织类型在销售渠道下级，需要向上反查，获取对应的销售渠道组织id，再查询对应的审批节点，未找到返回；
        //        若组织类型在销售渠道上级，需继续向上反查，获取对应的业务单元组织ID，再查询对应的审批节点（可能存在多个），未找到返回
        // step2、判断当前提报人的组织类型、角色是否在审批节点配置中，如果不在，则不允许提交
        // step3、判断当前提报人的组织类型和对应角色是否位于第一节点 只有审批流程中第一节点需要校验月度计划明细的完成度，其它节点不需要进行校验
        // step4、若当前是第一节点，通过月度计划id和组织id获取对应的提报单，若没有提报单则需要校验月度计划明细的完成度。若有提报单，不需要校验
        // step5、若有多个审批配置，循环处理
        List<AuditSetting> auditSettings = getAuditConfiguration(salesPlanReportRequest);
        //获取所有角色信息
        Map</*code*/String, /*id*/String> roleSDOMap = getRoleSDOMap();
        //有任意配置满足条件，就终止循环；如果所有配置都不满足，就抛出异常
//        boolean isBreak = true;
        // 记录当前循环次数
        int num = 0;
        for (AuditSetting auditSetting :auditSettings) {
            try {
                num++;
                // 校验提报配置,获取提报人能够审批的节点
                Map<String, List<AuditSettingDetail>> map = checkReportSetting(auditSetting, roleSDOMap, salesPlanReportRequest.getRelationOrganizationType(), salesPlanReportRequest.getRoleCodes());
                //按照审批顺序，判断命中哪一条审批节点
                List<AuditSettingDetail> permitList = map.get(PERMIT_LIST);
                List<AuditSettingDetail> lastSequenceList = map.get(LAST_SEQUENCE_LIST);
                permitList.stream().sorted(Comparator.comparing(AuditSettingDetail::getAuditSequence)).forEach(auditSettingDetail -> {
                    // 当前处于审批配置最后一个节点，不需要提报
                    if (auditSettingDetail.getAuditSequence().equals(lastSequenceList.get(0).getAuditSequence())) {
                        log.info("SalesPlanReportWriteService.report当前提报人位于审批配置最后节点={}", JSONObject.toJSONString(auditSetting));
                        throw new FacadeException(ErrorMessage.code("OTS-02-002-01-16-027"));
                    }
                    // 审批配置中的第一节点需要校验角色权限内的所有月度计划明细
//                    if (auditSettingDetail.getAuditSequence() == 1) {
                        // 业务限制校验
                        checkBizRule(salesPlanReportRequest, auditSettingDetail, roleSDOMap);
//                    }
                    // step6、构建提报单数据
                    SalesPlanReportSDO salesPlanReportSDO = buildSalesPlanReportSDO(salesPlanReportRequest, auditSettingDetail, roleSDOMap);
                    log.info("SalesPlanReportWriteService.report.salesPlanReportSDO={}", JSONObject.toJSONString(salesPlanReportSDO));
                    // step7、是否存在前序提报单
                    fetchPreReport(salesPlanReportSDO, auditSettingDetail.getAuditSequence());

                    String salesPlanReportId;
                    // 当前提报单存在
                    List<SalesPlanReportSDO> salesPlanReportSDOList = salesPlanReportRepository.querySalesPlanReportList(convertQuerySalesPlanReportRequest(salesPlanReportSDO));
                    if (CollectionUtils.isEmpty(salesPlanReportSDOList)) {
                        // 生成当前提报单和父级id
                        salesPlanReportId = saveReport(salesPlanReportSDO, salesPlanReportRequest, auditSettingDetail, auditSetting,lastSequenceList);
                    } else {
                        // 月度计划每个维度只有一个提报单
                        SalesPlanReportSDO salesPlanReportSDORecord = salesPlanReportSDOList.get(0);
                        // 判断是否有未审批的任务
                        if (SalesPlanReportAuditStatusEnum.UNDER_REVIEW.getCode().equals(salesPlanReportSDORecord.getAuditStatus())) {
                            throw new FacadeException(ErrorMessage.code("OTS-02-003-01-16-011"));
                        }
                        // 更新提报单状态为已提报
                        updateReport(salesPlanReportSDORecord);
                        salesPlanReportId = salesPlanReportSDORecord.getId();
                    }
                    // todo 以上db操作可以放在事务内，防止审批流节点启动失败
                    // 设置提报单id
                    salesPlanReportSDO.setId(salesPlanReportId);
                    // 创建审批流和启动审配引擎
                    log.info("SalesPlanReportWriteService.report.startUpAuditFlow.request={}", JSONObject.toJSONString(salesPlanReportSDO));
                    startUpAuditFlow(salesPlanReportSDO, salesPlanReportRequest, auditSettingDetail, auditSetting);
                    // 发送汇总消息，防止页面没有汇总就提报
                    String planId = salesPlanReportRequest.getPlanId();
                    try {
                        // 发消息，触发汇总
                        log.info("report_sales_plan_publish_message{}", planId);
                        Boolean aBoolean = messageService.sendMessage("sales_plan_publish_message", "CR_SALES_PLAN", "salesPlan_collect", planId);
                    } catch (Exception e) {
                        log.error("SalesPlanReportWriteServiceImpl#report fail-" + "提交审批触发月度计划汇总消息发送异常", e);
                    }
                });
//                isBreak = false;
                break;
            } catch (FacadeException facadeException) {
                log.error("提报人id=" + JSONObject.toJSONString(salesPlanReportRequest.getOperatorId()) + "SalesPlanReportWriteService.report.auditSetting=" + JSONObject.toJSONString(auditSetting) + ",facadeException=" + JSONObject.toJSONString(facadeException));
                if(auditSettings.size() == 1 || auditSettings.size()  == num) {
                    return Result.fail(false, facadeException.getErrorCode(), facadeException.getErrorMessage());
                }
            }
        }
//        if (isBreak) {
//            return Result.fail(false, "OTS-02-003-01-16-037", ErrorMessage.code("OTS-02-003-01-16-037", null).getDisplayErrorMessage());
//        }
        return Result.success(true);
    }

    /**
     * 检查提报配置,获取提报人能够审批的节点
     * @return boolean
     */
    private Map<String, List<AuditSettingDetail>> checkReportSetting(AuditSetting audit, Map<String, String> roleSDOMap, Integer OrganizationType, List<String> roleCodes) {
        List<AuditSettingDetail> auditDetails = obtainAuditSettingDetail(audit);
        if (CollectionUtils.isEmpty(auditDetails)) {
            log.error("SalesPlanReportWriteService.checkReportSetting当前审批主单id=" + audit.getId()+ "settingDetail=" + JSONObject.toJSONString(audit));
            throw new FacadeException(ErrorMessage.code("OTS-02-002-01-16-025"));
        }
        Map<String, AuditSettingDetail> detailMap = Maps.newHashMap();
        auditDetails.forEach(auditDetail -> {
            String organizationType = auditDetail.getOrganizationType();
            String roleId = auditDetail.getRoleId();
            if (Objects.isNull(detailMap.get(organizationType + roleId))) {
                detailMap.put(organizationType + roleId, auditDetail);
            }
        });
        List<AuditSettingDetail> permitList = Lists.newArrayList();
        roleCodes.forEach(code -> {
            AuditSettingDetail auditSettingDetail = detailMap.get(OrganizationType + roleSDOMap.get(code));
            if (!Objects.isNull(auditSettingDetail)) {
                permitList.add(auditSettingDetail);
            }
        });
        if (CollectionUtils.isEmpty(permitList)) {
            log.error("SalesPlanReportWriteService.checkReportSetting.当前提报人未配置审批节点：{}", JSONObject.toJSONString(audit));
            throw new FacadeException(ErrorMessage.code("OTS-02-002-01-16-026"));
        }
        List<AuditSettingDetail> lastSequenceList = Lists.newArrayList();
        lastSequenceList.add(auditDetails.stream()
                .max(Comparator.comparingInt(AuditSettingDetail::getAuditSequence))
                .orElse(new AuditSettingDetail()));
        Map<String, List<AuditSettingDetail>> map = new HashMap<>();
        map.put(PERMIT_LIST, permitList);
        map.put(LAST_SEQUENCE_LIST, lastSequenceList);
        return map;
    }

    private Map<String, String> getRoleSDOMap() {
        Map<String, String> roleSDOMap = new HashMap<>();
        Result<List<RoleSDO>> result = bcOtsService.getAllRoles(GetAllRolesRequest.builder().belongOrganizationId("1").build());
        if (!result.isSuccess() || org.apache.commons.collections4.CollectionUtils.isEmpty(result.getResult())) {
            log.info("查询角色信息失败AuditSettingDetailService.convertResponseList");
        } else {
            roleSDOMap = result.getResult().stream().collect(Collectors.toMap(RoleSDO::getCode, RoleSDO::getId, (a, b) -> a));
        }
        return roleSDOMap;
    }

    /**
     * 获取当前审批配置的下一节点
     * @return
     */
    private AuditSettingDetail obtainNextAuditSettingDetail(AuditSettingDetail detailSetting, AuditSetting audit) {
        List<AuditSettingDetail> auditDetails = obtainAuditSettingDetail(audit);
        List<AuditSettingDetail> list = auditDetails.stream().filter(detail -> {
            return detail.getAuditSequence() == detailSetting.getAuditSequence() + 1;
        }).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(list)) {
            return new AuditSettingDetail();
        }
        return list.get(0);
    }


    /**
     * 获取审批配置
     * @param request request
     */
    private List<AuditSetting> getAuditConfiguration(SalesPlanReportRequest request) {
        log.info("SalesPlanReportWriteService.getAuditConfiguration.request=" + JSONObject.toJSONString(request));
        SalesPlanReportRequest salesPlanRequest = new SalesPlanReportRequest();
        BeanUtils.copyProperties(request, salesPlanRequest);
        // 当前为销售渠道，或销售单元可直接获取对应审批配置
        if (OrganizationTypeEnum.SALES_CHANNEL.getCode().equals(request.getRelationOrganizationType()) ||
                OrganizationTypeEnum.COMPANY.getCode().equals(request.getRelationOrganizationType())) {
            salesPlanRequest.setRelationOrganizationId(request.getRelationOrganizationId());
        } else if (OrganizationTypeEnum.SALES_DEPARTMENT.getCode().equals(request.getRelationOrganizationType())) {
            // 向上反查对应组织id
            OrganizationSDO organizationSDO = obtainUpOrganization(request.getRelationOrganizationId(), OrganizationTypeEnum.SALES_CHANNEL.getCode());
            salesPlanRequest.setRelationOrganizationId(organizationSDO.getId());
            salesPlanRequest.setRelationOrganizationType(OrganizationTypeEnum.SALES_CHANNEL.getCode());
        } else if (OrganizationTypeEnum.SALES_ORGANIZATION.getCode().equals(request.getRelationOrganizationType())) {
            // 向上反查对应组织id
            OrganizationSDO organizationSDO = obtainUpOrganization(request.getRelationOrganizationId(), OrganizationTypeEnum.COMPANY.getCode());
            salesPlanRequest.setRelationOrganizationId(organizationSDO.getId());
            salesPlanRequest.setRelationOrganizationType(OrganizationTypeEnum.COMPANY.getCode());
        } else  {
            throw new FacadeException(ErrorMessage.code("OTS-02-002-01-16-024"));
        }
        log.info("SalesPlanReportWriteService.obtainAuditSetting.request={}", JSONObject.toJSONString(salesPlanRequest));
        List<AuditSetting> auditSettings = obtainAuditSetting(salesPlanRequest);
        if (CollectionUtils.isEmpty(auditSettings)) {
            throw new FacadeException(ErrorMessage.code("OTS-02-002-01-16-023"));
        }
        return auditSettings;
    }

    /**
     * 获取当前审批人的上级组织
     * @return
     */
    private OrganizationSDO obtainUpOrganization(String relationOrganizationId, Integer upOrganizationType) {
        // 获取当前组织向上回溯指定类型组织列表
        List<OrganizationSDO> organizationSDOList = platformEnhanceRepository.getTopOrganizationList(convert(relationOrganizationId, upOrganizationType));
        if (CollectionUtils.isEmpty(organizationSDOList)) {
            throw new FacadeException(ErrorMessage.code("OTS-02-003-01-16-013"));
        }
        // 获取最后一个组织即可
        return organizationSDOList.get(organizationSDOList.size() - 1);
    }

    /**
     * 获取审批配置主单信息
     * @param request request
     * @return result
     */
    private List<AuditSetting> obtainAuditSetting(SalesPlanReportRequest request) {
        // 获取审批配置主单、可能有多个
        Result<List<AuditSetting>> result = auditSettingService.loadList(buildAuditSettingRequest(request));
        if (!result.isSuccess() || CollectionUtils.isEmpty(result.getResult())) {
            return Lists.newArrayList();
        }
        return result.getResult();
    }

    /**
     * 通过审批主单id获取审批配置子单信息
     * @param request request
     * @return result
     */
    private List<AuditSettingDetail> obtainAuditSettingDetail(AuditSetting request) {
        Result<List<AuditSettingDetail>> result = auditSettingDetailService.loadList(buildAuditSettingDetailRequest(request));
        if (!result.isSuccess() || CollectionUtils.isEmpty(result.getResult())) {
            return Lists.newArrayList();
        }
        return result.getResult();
    }

    private AuditSettingLoadListRequest buildAuditSettingRequest(SalesPlanReportRequest request) {
        AuditSettingLoadListRequest auditSettingRequest = new AuditSettingLoadListRequest();
        auditSettingRequest.setStatus(AuditSettingStatusEnum.ENABLE.getType());
        if (SalesPlanModelEnum.PLAN_MODEL.getModel().equals(request.getModel())) {
            auditSettingRequest.setType(AuditSettingTypeEnum.SALES_PLAN_REPORT.getType());
        } else if (SalesPlanModelEnum.ADJUST_MODEL.getModel().equals(request.getModel())) {
            auditSettingRequest.setType(AuditSettingTypeEnum.SALES_PLAN_ADJUST.getType());
        }
        if (OrganizationTypeEnum.SALES_DEPARTMENT.getCode().equals(request.getRelationOrganizationType()) ||
        OrganizationTypeEnum.SALES_CHANNEL.getCode().equals(request.getRelationOrganizationType())) {
            auditSettingRequest.setOrgChannelCode(request.getRelationOrganizationId());
        } else if (OrganizationTypeEnum.SALES_ORGANIZATION.getCode().equals(request.getRelationOrganizationType()) ||
        OrganizationTypeEnum.COMPANY.getCode().equals(request.getRelationOrganizationType())) {
            auditSettingRequest.setOrgBusinessUnitCode(request.getRelationOrganizationId());
        }
        log.info("SalesPlanReportWriteService.buildAuditSettingRequest.request={}", JSONObject.toJSONString(auditSettingRequest));
        return auditSettingRequest;
    }

    private AuditSettingDetailLoadListRequest buildAuditSettingDetailRequest(AuditSetting request) {
        AuditSettingDetailLoadListRequest detailRequest = new AuditSettingDetailLoadListRequest();
        detailRequest.setAuditSettingId(request.getId());
        detailRequest.setStatus(AuditSettingStatusEnum.ENABLE.getType());
        return detailRequest;
    }

    /**
     * 重写校验提报业务
     * @param reportRequest 入参
     */
    private void checkBizRule(SalesPlanReportRequest reportRequest, AuditSettingDetail auditSettingDetail, Map<String, String> roleSDOMap) {
        // 月度计划调整无需校验计划明细
        if (SalesPlanModelEnum.ADJUST_MODEL.getModel().equals(reportRequest.getModel())) {
            return;
        }
        // 提报人数据权限范围内的计划明细
        PageQueryPlanLineRequest request = new PageQueryPlanLineRequest();
        refreshPageQueryPlanLineRequest(reportRequest, request, auditSettingDetail, roleSDOMap);
        log.info("SalesPlanReportWriteService.report.checkBizRule.pageQuerySalesPlanLineList.request={}", JSONObject.toJSONString(request));
        PageResult<List<SalesPlanLineSDO>> pageResult = salesPlanLineRepository.pageQuerySalesPlanLineList(request);
        if (null != pageResult && CollectionUtils.isNotEmpty(pageResult.getContent())) {
            throw new FacadeException(ErrorMessage.code("OTS-02-003-01-16-021"));
        }
    }

    private void refreshPageQueryPlanLineRequest(SalesPlanReportRequest reportRequest, PageQueryPlanLineRequest request,
                                                 AuditSettingDetail auditSettingDetail, Map<String, String> roleSDOMap) {
        // 当前审批节点是业务员需要以业务员身份获取月度计划明细数据
        if (auditSettingDetail.getRoleId().equals(roleSDOMap.get(RoleCodeEnum.SALE_MAN.getCode()))) {
            log.info("SalesPlanReportWriteService.report.checkBizRule.refreshPageQueryPlanLineRequest业务员提报");
            request.setManageEmployeeId(reportRequest.getOperatorId());
        } else {
            OrganizationTypeEnum organizationTypeEnum = OrganizationTypeEnum.of(reportRequest.getRelationOrganizationType());
            switch (organizationTypeEnum) {
                case COMPANY:
                    request.setOrgBusinessUnitCode(reportRequest.getRelationOrganizationId());
                    break;
                case SALES_ORGANIZATION:
                    request.setOrgSalesOrganizationCode(reportRequest.getRelationOrganizationId());
                    break;
                case SALES_CHANNEL:
                    request.setOrgSalesChannelCode(reportRequest.getRelationOrganizationId());
                    break;
                case SALES_DEPARTMENT:
                    request.setOrgSalesDepartmentCode(reportRequest.getRelationOrganizationId());
                    break;
                default:
            }
        }
        request.setPlanId(reportRequest.getPlanId());
        // 标识提报量小于1
        request.setMonthCount(1);
        request.setStart(0);
        request.setLimit(1);
    }

    /**
     * 重写查询前序提报单
     * @param salesPlanReportSDO 入参
     * @param auditSequence 结果
     * @return
     */
    private List<SalesPlanReportSDO> fetchPreReport(SalesPlanReportSDO salesPlanReportSDO, Integer auditSequence) {
        // todo 除了第一节点不需要查询以外，其它节点都需要查询
        if (1 == auditSequence) {
            return Lists.newArrayList();
        }
        List<SalesPlanReportSDO> exSalesPlanReportSDOs = Lists.newArrayList();
        QuerySalesPlanReportRequest exQuerySalesPlanReportRequest = new QuerySalesPlanReportRequest();
        exQuerySalesPlanReportRequest.setPlanId(salesPlanReportSDO.getPlanId());
        exQuerySalesPlanReportRequest.setModelId(salesPlanReportSDO.getModelId());
        exQuerySalesPlanReportRequest.setModel(salesPlanReportSDO.getModel());
        exQuerySalesPlanReportRequest.setParentId(salesPlanReportSDO.getBizId());
        // 判断是否有未完成的子提报单
        log.info("SalesPlanReportWriteService.report.fetchPreReport.exQuerySalesPlanReportRequest={}", JSONObject.toJSONString(exQuerySalesPlanReportRequest));
        exSalesPlanReportSDOs = salesPlanReportRepository.querySalesPlanReportList(exQuerySalesPlanReportRequest);
        log.info("SalesPlanReportWriteService.report.fetchPreReport.exSalesPlanReportSDOs={}", JSONObject.toJSONString(exSalesPlanReportSDOs));
        if (CollectionUtils.isNotEmpty(exSalesPlanReportSDOs)) {
            // 判断子提审单是否都完成  通过认定为终态
            boolean flag = exSalesPlanReportSDOs.stream().anyMatch(s -> !s.getAuditStatus().equals(SalesPlanReportAuditStatusEnum.APPROVED.getCode()));
            // 前序未审核完成, 不能创建提报单
            if (flag) {
                throw new FacadeException(ErrorMessage.code("OTS-02-003-01-16-008"));
            }
        } else {
            // 无前序提报单，需要报错
            throw new FacadeException(ErrorMessage.code("OTS-02-003-01-16-009"));
        }
        return exSalesPlanReportSDOs;
    }

    /**
     * 重写保存提报单
     * @param salesPlanReportSDO 月度计划提报入参
     * @param detailSetting 审批明细
     * @param audit 审批主单
     * @return 提报单id
     */
    private String saveReport(SalesPlanReportSDO salesPlanReportSDO, SalesPlanReportRequest salesPlanReportRequest, AuditSettingDetail detailSetting, AuditSetting audit, List<AuditSettingDetail> lastSequenceList) {
        log.info("SalesPlanReportWriteService.report.saveReport.salesPlanReportSDO={}", JSONObject.toJSONString(salesPlanReportSDO));
        log.info("SalesPlanReportWriteService.report.saveReport.auditSettingDetail={}", JSONObject.toJSONString(detailSetting));
        log.info("SalesPlanReportWriteService.report.saveReport.auditSetting={}", JSONObject.toJSONString(audit));
        // 构造当前维度提报单
        SalesPlanReportSDO salesPlanSDOForCreate = new SalesPlanReportSDO();
        BeanUtils.copyProperties(salesPlanReportSDO, salesPlanSDOForCreate);
        salesPlanSDOForCreate.setStatus(SalesPlanReportStatusEnum.REPORTED.getCode());
        // 获取父级节点
        AuditSettingDetail settingDetail = obtainNextAuditSettingDetail(detailSetting, audit);
        // 父级节点是最后一个节点，无需保存父级节点id
        if (!lastSequenceList.get(0).getAuditSequence().equals(settingDetail.getAuditSequence())) {
            OrganizationSDO organization = obtainUpOrganization(salesPlanReportRequest.getRelationOrganizationId(), Integer.parseInt(settingDetail.getOrganizationType()));
        // todo 通过父级节点类型获取bizId
        // 保存父级节点id
            salesPlanSDOForCreate.setParentId(organization.getId());
        }
        SalesPlanReportEntity salesPlanReportEntity = SalesPlanReportEntity.of(salesPlanSDOForCreate);
        return salesPlanReportEntity.save();
    }

    /**
     * 重写开启审批流
     * @param salesPlanReportSDO 月度计划提报入参
     */
    private void startUpAuditFlow(SalesPlanReportSDO salesPlanReportSDO, SalesPlanReportRequest salesPlanReportRequest, AuditSettingDetail auditSettingDetail, AuditSetting auditSetting) {
        // 创建审批单
        String auditId = createSalesPlanAudit(salesPlanReportSDO);
        // 插入审批单明细（快照）TODO 审核单明细暂时不保存
        // createSalesPlanAuditLine(auditId, salesPlanReportSDO);
        // 创建纪元审批流实例、并启动（审批单ID）
        FlowInstanceStartUpResponse flowInstanceStartUpResponse = null;
        try {
            AuditSettingDetail parentAuditSettingDetail = obtainNextAuditSettingDetail(auditSettingDetail, auditSetting);
            List<String> auditorIdList = getAuditorList(salesPlanReportRequest.getRelationOrganizationId(), parentAuditSettingDetail);
            flowInstanceStartUpResponse = startUpAudit(auditId, salesPlanReportSDO, auditorIdList);
            log.info("启动审批流返回结果：{}", JSONObject.toJSONString(flowInstanceStartUpResponse));
        } catch (FacadeException facadeException) {
            log.error("SalesPlanReportWriteServiceImpl#report_fail " + "启动审批流发生异常:{}-{}", facadeException.getErrorCode(), facadeException.getErrorMessage());
            throw facadeException;
        } catch (Exception e) {
            log.error("SalesPlanReportWriteServiceImpl#report_fail " + "启动审批流异常", e);
            throw new FacadeException(ErrorMessage.code("OTS-02-003-01-16-012"));
        }
    }

    /**
     * 获取审批人列表
     *
     * @param organizationId 组织id
     * @param auditSettingDetail 父级审批节点
     * @return 审批人
     */
    private List<String> getAuditorList(String organizationId, AuditSettingDetail auditSettingDetail) {
        Map<String, String> roleSDOMap = new HashMap<>();
        Result<List<RoleSDO>> result = bcOtsService.getAllRoles(GetAllRolesRequest.builder().belongOrganizationId("1").build());
        if (!result.isSuccess() || org.apache.commons.collections4.CollectionUtils.isEmpty(result.getResult())) {
            log.info("查询角色信息失败AuditSettingDetailService.convertResponseList");
        } else {
            roleSDOMap = result.getResult().stream().collect(Collectors.toMap(RoleSDO::getId, RoleSDO::getCode, (a, b) -> a));
        }
        // 获取当前组织向上回溯指定类型组织列表
        OrganizationSDO organization = obtainUpOrganization(organizationId, Integer.parseInt(auditSettingDetail.getOrganizationType()));
        // 通过审批配置列表获取下一级组织id，角色类型，查询组织下的所有用户
        List<EmployeeSDO> employeeSDOS = platformEnhanceRepository.getEmployeeList(organization.getId(), 1);
        if (CollectionUtils.isEmpty(employeeSDOS)) {
            throw new FacadeException(ErrorMessage.code("OTS-02-003-01-16-014"));
        }
        // 根据角色过滤
        List<String> auditorIdList = filterEmployeeByRole(roleSDOMap.get(auditSettingDetail.getRoleId()), employeeSDOS);
        if (CollectionUtils.isEmpty(auditorIdList)) {
            throw new FacadeException(ErrorMessage.code("OTS-02-003-01-16-014"));
        }
        return auditorIdList.stream().map(id -> "CZ_" + id).collect(Collectors.toList());
    }

    /**
     * 根据角色筛选员工id
     * 主要解决同一组织多个角色问题
     *
     * @param roleCode
     * @param employeeSDOS
     * @return
     */
    private List<String> filterEmployeeByRole(String roleCode, List<EmployeeSDO> employeeSDOS) {

        if (Objects.nonNull(RoleCodeEnum.of(roleCode))) {
            return filter(employeeSDOS, RoleCodeEnum.of(roleCode).getCode()).stream().map(EmployeeSDO::getId).collect(Collectors.toList());
        }
        return employeeSDOS.stream().map(EmployeeSDO::getId).collect(Collectors.toList());
    }

    /**
     * 重写构建月度计划提报数据
     * @param salesPlanReportRequest 入参
     * @param roleSDOMap 入参
     * @return 结果
     */
    private SalesPlanReportSDO buildSalesPlanReportSDO(SalesPlanReportRequest salesPlanReportRequest, AuditSettingDetail detail,
                                                       Map<String, String> roleSDOMap) {
        log.info("SalesPlanReportWriteService.report.buildSalesPlanReportSDO.salesPlanReportRequest={}", JSONObject.toJSONString(salesPlanReportRequest));
        log.info("SalesPlanReportWriteService.report.buildSalesPlanReportSDO.auditSettingDetail={}", JSONObject.toJSONString(detail));
        // 获取提拔单维度信息
        SalesPlanReportSDO salesPlanReportSDO = getReportDimension(salesPlanReportRequest, detail, roleSDOMap);
        // 属性封装
        salesPlanReportSDO.setPlanId(salesPlanReportRequest.getPlanId());
        salesPlanReportSDO.setModel(salesPlanReportRequest.getModel());
        salesPlanReportSDO.setModelId(salesPlanReportRequest.getModelId());
        salesPlanReportSDO.setPlanTime(salesPlanReportRequest.getPlanTime());
        salesPlanReportSDO.setReportEmployeeId(salesPlanReportRequest.getOperatorId());
        salesPlanReportSDO.setAuditStatus(SalesPlanReportAuditStatusEnum.UNDER_REVIEW.getCode());
        salesPlanReportSDO.setCreatorId(salesPlanReportRequest.getOperatorId());
        salesPlanReportSDO.setModifierId(salesPlanReportRequest.getOperatorId());
        return salesPlanReportSDO;
    }

    /**
     * 重写获取提报维度
     * @param salesPlanReportRequest 入参
     * @param roleSDOMap 入参
     * @return 结果
     */
    private SalesPlanReportSDO getReportDimension(SalesPlanReportRequest salesPlanReportRequest, AuditSettingDetail detail,
                                                  Map<String, String> roleSDOMap) {
        Integer relationOrganizationType = salesPlanReportRequest.getRelationOrganizationType();
        SalesPlanReportSDO salesPlanReportSDO = new SalesPlanReportSDO();
        //TODO
        salesPlanReportSDO.setIsLeafTask(0);
        // 1、业务员（业务员角色）
        if (detail.getRoleId().equals(roleSDOMap.get(RoleCodeEnum.SALE_MAN.getCode()))) {
            log.info("SalesPlanReportWriteService.report.checkBizRule.refreshPageQueryPlanLineRequest业务员提报");
            salesPlanReportSDO.setBizType(SalesPlanReportBizTypeEnum.PROMOTER_REPORT.getCode());
            salesPlanReportSDO.setBizId(salesPlanReportRequest.getOperatorId());
            salesPlanReportSDO.setIsLeafTask(1);
        }
        // 2、销售部门
        else if (OrganizationTypeEnum.SALES_DEPARTMENT.getCode().equals(relationOrganizationType)) {
            salesPlanReportSDO.setBizType(SalesPlanReportBizTypeEnum.DEPARTMENT_REPORT.getCode());
            salesPlanReportSDO.setBizId(salesPlanReportRequest.getRelationOrganizationId());
        }
        // 3、销售渠道（渠道经理角色）
        else if (OrganizationTypeEnum.SALES_CHANNEL.getCode().equals(relationOrganizationType)) {
            salesPlanReportSDO.setBizType(SalesPlanReportBizTypeEnum.CHANNEL_REPORT.getCode());
            salesPlanReportSDO.setBizId(salesPlanReportRequest.getRelationOrganizationId());
        }
        // 4、销售组织
        else if (OrganizationTypeEnum.SALES_ORGANIZATION.getCode().equals(relationOrganizationType)) {
            salesPlanReportSDO.setBizType(SalesPlanReportBizTypeEnum.ORGANIZATION_REPORT.getCode());
            salesPlanReportSDO.setBizId(salesPlanReportRequest.getRelationOrganizationId());
        }
        // 5、业务单元（调度员/总经理角色）
        else if (OrganizationTypeEnum.COMPANY.getCode().equals(relationOrganizationType)) {
            salesPlanReportSDO.setBizType(SalesPlanReportBizTypeEnum.BUSINESS_DIMENSION_REPORT.getCode());
            salesPlanReportSDO.setBizId(salesPlanReportRequest.getRelationOrganizationId());
        }
        // 其他角色先默认为业务员（如：平台超级管理员）
        else {
            salesPlanReportSDO.setBizType(SalesPlanReportBizTypeEnum.PROMOTER_REPORT.getCode());
            salesPlanReportSDO.setBizId(salesPlanReportRequest.getOperatorId());
            salesPlanReportSDO.setIsLeafTask(1);
        }
        return salesPlanReportSDO;
    }

}
